<?php
class Passport_Weixin
{
    const OPENID_URL = 'https://api.weixin.qq.com/sns/oauth2/access_token?';
    const TOKEN_URL = 'https://api.weixin.qq.com/cgi-bin/token?';
    const USERINFO_URL = 'https://api.weixin.qq.com/cgi-bin/user/info?';

    private static $_instance = null;
    private $_config = array();

    public static function getCurrentUserInfo ()
    {
        require_once (DOCROOT.'/resource/wxpay/example/WxPay.JsApiPay.php');
        $api = new JsApiPay;

        // get OpenId
        $openId    = $api->getOpenId();
        $appId     = WxPayConfig::APPID;
        $appSecret = WxPayConfig::APPSECRET;
        
        // get UserInfo
        $config = array('appid' => $appId, 'appsercert' => $appSecret);
        $wx = new Passport_Weixin($config);
        $info   = $wx->get_userinfo($openId);

        return $info;
    }
    
    private function __construct($config)
    {
        $this->_config = $config;
    }

    public function get_access_token()
    {
        $key = '_WX_ACCESS_TOKEN_'.$this->_config['appid'];
        $cache = Cache::instance('file');
        $access_token = $cache->get($key);
        if($access_token)
        {
            return $access_token;
        }
        else
        {
            $param['grant_type']= 'client_credential';
            $param['appid']     = $this->_config['appid'];
            $param['secret']    = $this->_config['appsercert'];
            $url = self::TOKEN_URL . http_build_query($param);
            $json = json_decode(self::http_get($url), true);
            if (!empty($json['access_token']))
            {
                $cache->set($key, $json['access_token']);                          
                return $json['access_token'];
            }
            return false;
        }
    }

    public function get_openid($code, $n = 10)
    {
        $param['appid']     = $this->_config['appid'];
        $param['secret']    = $this->_config['appsercert'];
        $param['code']      = $code;
        $param['grant_type']= 'authorization_code';
        $url = self::OPENID_URL . http_build_query($param);

        $json = self::http_get($url);
        $data = json_decode($json, TRUE);
        if(!empty($data['openid']))
        {
            return $data['openid'];
        }
        else
        {
            if ($n < 0) 
            {
                Kohana::$log->add(Log::ERROR, "NOT FOUND openid: $code");
                return FALSE;
            }
            else
                return $this->get_openid($code, $n - 1);
        }
    }
    
    /**
     * 获取用户基本信息 subscribe为0说明用户还未关注
     *
     * @param unknown_type $openid
     * @return array
     */
    public function get_userinfo($openid)
    {
        $param['access_token']  = $this->get_access_token();
        $param['openid']        = $openid;
        $param['lang']          = 'zh_CN';
        $url = self::USERINFO_URL . http_build_query($param);
        $json = self::http_get($url);
        return json_decode($json, true);
    }


    /**
     * 进行get请求
     *
     * @param string $url
     * @return string
     */
    public static function http_get($url)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
        curl_setopt($ch, CURLOPT_TIMEOUT, 5);
        $rs = curl_exec($ch);
        $info = curl_getinfo($ch);
        curl_close($ch);
        return intval($info["http_code"]) == 200 ? $rs : false;
    }

    /**
     * 进行post请求
     *
     * @param string $url
     * @param array $data
     * @return string
     */
    public static function http_post($url, $data)
    {
        $ch = curl_init();
        if (is_array($data))
        {
            $data = http_build_query($data);
        }
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_TIMEOUT, 5);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        $rs = curl_exec($ch);
        $info = curl_getinfo($ch);
        curl_close($ch);
        return intval($info["http_code"]) == 200 ? $rs : false;
    }
}
